/**
 * @brief 通过HTTP(S)下载文件的模块
 * @version 1.0
 * @author 宋炜
 */
#pragma once
#include <string>
#include <utility>
#include <list>
#include <memory>
#include <functional>

#include <curl/curl.h>

#include "ary_str.hpp"
#include "threadPool.hpp"
#include "details/fileSvrItfc.hpp"
#include "timer.hpp"
namespace wheels {
	class curlHttp : public iFileService
	{
        friend size_t curlHttp_write_callback(char *ptr, size_t size, size_t nmemb, void *obj );
	public:
		// 要下载的文件和下载目标
		using fileRecord_t = std::pair<std::string , std::string>;
        using files_t = std::list<fileRecord_t >;

        static const long DEFAULT_BUFFER_SIZE; // 默认5M的下载内存缓冲
        static const int DEFAULT_THD_COUNT;
        static const long DEFAULT_OVERTIME;                // http通讯超时时间
	private:
		std::atomic< long >              m_buff_size__;
		std::shared_ptr< files_t >       m_files__;          // 如果使用延迟异步下载，所有要下载的目标路径添加在这里
		std::shared_ptr< threadPool >    pt_thd_pool__;      // 使用延迟异步下载的线程池
		std::mutex                       m_mutex__;
        std::function< bool ( emErrCode , uint8_t * , size_t ) >         m_cb__;
        std::function< bool ( emErrCode , size_t , int , const std::string& ) >   m_cb1__;
		CTimer                           m_timer__;
        std::atomic< long >              m_overtime__;
	private:
		/**
		 * @brief 执行一次下载操作。
		 */
		bool download__( const std::string& from , const std::string& dest );
	public:
		curlHttp();
		~curlHttp();
		
		virtual void bufferSize( size_t s ) override;
        virtual void overtime( long seconds ) final{ m_overtime__ = seconds; }
		/**
		 * @brief 下载文件操作
		 * @param from[ I ]源文件
		 * @param dest[ I ]目标文件
		 * @param autoRun[ I ]，自动开始执行操作
		 * @return 操作成功返回true，否则返回false
		 */
		virtual bool download( const std::string& from , const std::string& dest = "" , bool autoRun = true ) override;
		/**
		 * @brief 下载操作函数。操作完成后使用回调函数通知操作结果
		 * @param cb , 操作完成后的回调函数。这个函数用来通知操作结果，函数的原型如下：
		 *             bool fun( errCode err , size_t dataSize , const std::string& fileStorePath );
		 */
		virtual void download( const std::string& from , const std::string& dest , std::function< bool ( emErrCode , uint8_t * ,size_t  ) > cb , bool autoRun = true ) override;
		/**
		 * @brief 将数据下载到内存中
		 */
		virtual void download( const std::string& from , char * buffer , std::function< bool ( emErrCode , uint8_t * ,size_t ) > cb , bool autoRun = true ) override;

		/**
		 * @brief 批量下载文件。
		 * @param from
		 * @param dest
		 * @param autoRun
		 * @return 成功操作返回true, 否则返回false
		 */
		virtual bool download( const ArrayString& from , const ArrayString& dest , bool autoRun = true ) override;
		/**
		 * @brief 批量下载文件，使用回调函数通知操作结果和过程
		 */
		virtual void download( const ArrayString& from , const ArrayString& dest , std::function< bool ( emErrCode , uint8_t * ,size_t ) > cb, bool autoRun = true ) override;
		/**
		 * @brief 上传文件到服务器
		 * @param file[ I ], 本地文件
		 * @param remote_file[ I ], 远程文件
		 * @param autoRun[ I ]，调用后是否自动运行，如果不是自动运行任务将在后台挂起
		 * @param cb[ I ], 进度回调函数用来通知上传进度
		 * @return 成功操作返回true，否则返回false
		 * @note 目前仅仅支持自动运行
		 */
		virtual bool upload( const std::string& file ,  const std::string& remote_file ,  bool autoRun = true ) override;
		virtual void upload( const std::string& file ,  const std::string& remote_file, std::function< bool ( emErrCode , size_t )> cb ,bool autoRun = true ) override;
		/**
		 * @brief 批量上传操作
		 * @param from[ I ]
		 * @param dest[ I ]
		 * @param autoRun[ I ]
		 */
		virtual bool upload( const ArrayString& from , bool autoRun = true ) override;
		virtual void upload( const ArrayString& file , std::function< bool ( emErrCode , size_t )> cb , bool autoRun ) override;
		/**
		 * @brief 删除远程文件
		 * @param rem[ I ] 远程文件名
		 */
		virtual bool del( const std::string& rem ) override;
		/**
		 * @brief 设置用户名和密码
		 */
		virtual void setUser( const std::string& acc , const std::string& pswd ) override;

		/**
		 * @brief 指定URL
		 */
		virtual void addUrl( const std::string& url ) override;
		virtual void run() override;
		virtual void run( std::function< bool ( emErrCode , size_t , int , const std::string& ) > cb ) override;
		/**
		 * @brief 列出远程目录内容
		 */
		virtual emErrCode ls( ArrayString& rst ) override;
		virtual void ls( std::function< void ( emErrCode , ArrayString& ) > cb ) override;
		/**
		 * @brief 和linux access函数一样，用来检查文件的可访问性
		 * @param url[ I ]， 要访问的文件的路径
		 * @param type[ I ]， 检查的类型
		 * @return 操作成功返回OK ，否则返回错误代码
		 */
		virtual emErrCode access( const std::string& url , int type ) override;
		/**
		 * @brief 切换远程目录路径
		 * @param path ， 路径字符串
		 */
		virtual emErrCode cd( const std::string& path ) override;
		/**
		 * @brief 读取远程文件的文件大小
		 * @param file[ I ] 文件路径
		 * @return 成功操作返回文件大小
		 */
		virtual size_t size( const std::string& file ) override;

        void on_recv__( const char * data , size_t len , std::shared_ptr< std::ofstream >);
	};
}
